Skip to content

Stage 2: ODBC pooling primitives (ADO #47338) - #296

Draft
Saurabh Singh (saurabh500) wants to merge 1 commit into
saurabh500-stage-1-tds-reset-correctnessfrom
saurabh500-stage-2-odbc-pooling-primitives
Draft

Stage 2: ODBC pooling primitives (ADO #47338)#296
Saurabh Singh (saurabh500) wants to merge 1 commit into
saurabh500-stage-1-tds-reset-correctnessfrom
saurabh500-stage-2-odbc-pooling-primitives

Conversation

@saurabh500

@saurabh500 Saurabh Singh (saurabh500) commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Stage 2 of the mssql-odbc connection pooling effort ([AB#47338](https://sqlclientdrivers.visualstudio.com/b95cf060-8083-439d-8ef1-405d5bf219d8/_workitems/edit/47338)). Wires the two ODBC pooling attributes into mssql-odbc, building on the Stage 1 TDS reset/liveness primitives.

B1 — Constants (api/odbc_types.rs)

  • SQL_ATTR_CONNECTION_DEAD = 1209, SQL_CD_TRUE = 1, SQL_CD_FALSE = 0
  • SQL_ATTR_RESET_CONNECTION = 116, SQL_RESET_CONNECTION_YES = 1

B2 — SQLGetConnectAttr(SQL_ATTR_CONNECTION_DEAD) (api/get_connect_attr.rs)

  • Returns SQL_CD_FALSE only when the DBC is connected and client.is_connection_dead() is false; otherwise SQL_CD_TRUE.
  • Disconnected / never-connected ⇒ SQL_CD_TRUE (D1: msodbcsql defaults DEAD until a successful token read).
  • Cached read, no network probe (D2). Peeks the client under the short DBC mutex — never take()s it (D8).

B3 — SQLSetConnectAttr(SQL_ATTR_RESET_CONNECTION, YES) (api/set_connect_attr.rs + api/txn.rs)

  • Routed from set_connect_attr.rs into a new reset_connection handler in txn.rs.
  • Value validation (D7): only SQL_RESET_CONNECTION_YES accepted; any other value ⇒ HY024.
  • Claims the idle client via claim_dbc_client (busy/active_stmt ⇒ connection-busy; disconnected ⇒ 08003, D7).
  • Rolls back a live local transaction first (D4), then arms the full reset via prepare_reset_connection(false) (pool checkout does not preserve).
  • Clears state.local_tran_started. Never holds the DBC mutex across I/O.
  • The bit rides the next request; the self-acking round-trip is deferred to Stage 3 (A2/B4).

B7 (partial) — Tests

  • SQL_ATTR_CONNECTION_DEAD: SQL_CD_TRUE when disconnected / connected-without-client; SQL_CD_FALSE when connected-and-alive; null-pointer rejected.
  • SQL_ATTR_RESET_CONNECTION: non-YES ⇒ HY024; disconnected ⇒ 08003; busy (active_stmt) rejected; success clears local_tran_started and leaves the idle client in place.

Validation

  • cargo bfmt
  • cargo bclippy ✅ (warnings-as-errors)
  • cargo nextest run -p mssql-odbc ✅ 573 passed

Stacking

This PR targets saurabh500-stage-1-tds-reset-correctness, not main. It is stacked on Stage 1 PR #294 (which stacks on base PR #293).

[AB#47338](https://sqlclientdrivers.visualstudio.com/b95cf060-8083-439d-8ef1-405d5bf219d8/_workitems/edit/47338)

Add SQL_ATTR_CONNECTION_DEAD and SQL_ATTR_RESET_CONNECTION support for
connection pooling (Stage 2, ADO #47338).

- B1: add SQL_ATTR_CONNECTION_DEAD/SQL_CD_TRUE/SQL_CD_FALSE and
  SQL_ATTR_RESET_CONNECTION/SQL_RESET_CONNECTION_YES constants.
- B2: SQLGetConnectAttr(SQL_ATTR_CONNECTION_DEAD) returns a cached,
  never-probe liveness read; disconnected/never-connected reads DEAD.
- B3: SQLSetConnectAttr(SQL_ATTR_RESET_CONNECTION) validates the value
  (HY024 otherwise), rolls back a live local transaction, arms the full
  RESETCONNECTION bit via prepare_reset_connection(false), and clears
  local_tran_started; disconnected surfaces 08003, busy is rejected.
- Unit tests cover both attributes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63e24621-7665-4572-a5b8-e5dfa55060a0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:connectionpool Work done for connection pool enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant